package cn.angleline.cloudhub.easbi

import au.com.console.jpaspecificationdsl.`in`
import au.com.console.jpaspecificationdsl.and
import au.com.console.jpaspecificationdsl.equal
import cn.angleline.cloudhub.easbi.eas.entity.*
import cn.angleline.cloudhub.easbi.util.EncryptUtils
import cn.angleline.cloudhub.easbi.yzj.entity.*
import com.fasterxml.jackson.databind.ObjectMapper
import com.google.common.cache.Cache
import okhttp3.*
import org.apache.commons.codec.digest.DigestUtils
import org.apache.commons.lang3.StringUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service
import java.math.BigDecimal
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.collections.set

@Service
class ReportApiService {

    @Autowired
    private lateinit var okHttpClient: OkHttpClient

    @Autowired
    private lateinit var tokenCache: Cache<String, String>

    @Autowired
    private lateinit var objectMapper: ObjectMapper

    @Autowired
    private lateinit var encryptUtils: EncryptUtils

    @Autowired
    private lateinit var paymentBillService: PaymentBillService

    @Autowired
    private lateinit var dataSourceRepo: DataSourceRepo

    @Autowired
    private lateinit var paymentBillRepo: TCasPaymentBillRepo

    @Autowired
    private lateinit var paymentEntityRepo: PaymentEntityRepo

    @Autowired
    private lateinit var receivingEntityRepo: ReceivingEntityRepo

    @Autowired
    private lateinit var tBgBgFormRepo: TBgBgFormRepo

    @Autowired
    private lateinit var tBgBgDataRepo: TBgBgDataRepo

    @Autowired
    private lateinit var tBgBgCtrlRecordRepo: TBgBgCtrlRecordRepo

    //资金预算
    @Autowired
    private lateinit var budgetDBRepo: BudgetDBRepo

    //收支汇总
    @Autowired
    private lateinit var incomeExpenseSummaryRepo: IncomeExpenseSummaryRepo

    //收款单汇总明细表
    @Autowired
    private lateinit var receivingSummaryRepo: ReceivingSummaryRepo

    //收款单明细表
    @Autowired
    private lateinit var receivingDetailRepo: ReceivingDetailRepo

    //付款单明细表
    @Autowired
    private lateinit var paymentDetailRepo: PaymentDetailRepo

    //付款单一级明细表
    @Autowired
    private lateinit var paymentFirstDetailRepo: PaymentFirstDetailRepo

    //付款单二级明细表
    @Autowired
    lateinit var paymentSecondDetailRepo: PaymentSecondDetailRepo

    @Autowired
    private lateinit var tOrgBaseUnitRepo: TOrgBaseUnitRepo

    @Value("\${cloudhub.app-id}")
    private lateinit var appId: String

    @Value("\${cloudhub.secret}")
    private lateinit var secret: String

    @Value("\${cloudhub.yzj-host}")
    private lateinit var host: String

    @Value("\${cloudhub.eid}")
    private lateinit var eid: String

    @Value("\${cloudhub.aes-key}")
    private lateinit var aesKey: String

    @Autowired
    private lateinit var tBgBgTemplateRepo: TBgBgTemplateRepo


    /**
     * 收支汇总数据源
     */
    object FundSumTable {
        const val tableInfoId = "5b768e2f870476120dd8fdeb"
        const val categoryId = "5b5ed7d8de02f61d7e17e555"
    }

    /**
     * 付款单一级明细表数据源
     */
    object PaymentFirstTable {
        const val tableInfoId = "5b7a80cc870476120dd908d4"
        const val categoryId = "5b4eb6d2de02f63889ff8762"
    }

    /**
     * 付款单二级明细表数据源
     */
    object PaymentSecondTable {
        const val tableInfoId = "5b7a87675ce367598eed6e9d"
        const val categoryId = "5b4eb6d2de02f63889ff8762"
    }

    /**
     * 付款单据数据源
     */
    object PaymentTable {
        const val tableInfoId = "5b6427355ce367135e5a1838"
        const val categoryId = "5b4eb6d2de02f63889ff8762"
    }

    /**
     * 收款单一级明细表数据源
     */
    object ReceivingSumTable {
        const val tableInfoId = "5b7e24935ce367598eed7eef"
        const val categoryId = "5b5ed7d8de02f61d7e17e555"
    }


    /**
     * 收款单据数据源
     */
    object ReceivingTable {
        const val tableInfoId = "5b64273d8704766ed043d9f2"
        const val categoryId = "5b5ed7d8de02f61d7e17e555"
    }

    /**
     * 资金预算单据数据源
     */
    object BudgetTable {
        const val tableInfoId = "5b860f4587047668058cd051"
        const val categoryId = "5b8525f8de02f6717d1ff834"
    }

    fun getAccessToken(): String {
        return tokenCache.get("accessToken") {
            val requestBuilder = Request.Builder()
            val urlBuilder = HttpUrl.Builder()
            //https://www.yunzhijia.com/gateway/oauth2/token/getAccessToken
            urlBuilder.scheme("https")
            urlBuilder.host("www.yunzhijia.com")
            urlBuilder.addPathSegment("gateway")
            urlBuilder.addPathSegment("oauth2")
            urlBuilder.addPathSegment("token")
            urlBuilder.addPathSegment("getTeamAccessToken")
            requestBuilder.url(urlBuilder.build())
            println("url-----" + urlBuilder.build().url().toString())
            val nonceStr = UUID.randomUUID().toString()
            val timeStamp = System.currentTimeMillis().toString()
            val signature = sign(appId, nonceStr, timeStamp, secret)
            val tokenEntity = TokenParam(appId, nonceStr, signature, timeStamp)

            val body = objectMapper.writeValueAsString(tokenEntity)
            requestBuilder.post(RequestBody.create(MediaType.parse("application/json"), body))

            val response = okHttpClient.newCall(requestBuilder.build()).execute()
            val responseBody = response.body()
            if (response.isSuccessful && responseBody != null) {
                val accessToken = objectMapper.readValue(
                        responseBody.byteStream(), AccessToken::class.java)
                System.out.println("-------------------------token--------" + accessToken.data)
                accessToken.data.accessToken
            } else {
                throw IllegalArgumentException("appId或secret不正确")
            }
        }
    }

    fun sign(vararg data: String): String {
        Arrays.sort(data)
        return DigestUtils.sha1Hex(StringUtils.join(*data))
    }

    //获取报表分类及数据表信息
    fun getAdminTableInfos() {

//        CategoryWithReportTableVo [id=5b4eb6dc91920e417b46f56d, name=收款单, tableInfos=[]],
//        CategoryWithReportTableVo [id=5b4eb6d2de02f63889ff8762, name=付款单, tableInfos=[]],
//        CategoryWithReportTableVo [id=5b4ef0d691920e417b472091, name=资金预算, tableInfos=[]]]
    }

    fun deleteData() {
        dataSourceRepo.deleteAll()
    }

    fun getAll(): List<DataSourceEntity> {
        return dataSourceRepo.findAll().toList()
    }

    fun getTestData() {
//        val list = paymentBillService.getYearDetailPaymentBill(Date())
        val list = paymentBillRepo.findAll().toList()
        println("*****************************")
        println(list.size)
        println("**************************")
    }

    fun getReceivingData() {
//        val list = paymentBillService.getYearDetailPaymentBill(Date())
        val list = receivingEntityRepo.findAll().toList()
        println("*****************************")
        println(list.size)
        println("**************************")
    }

    //判断是否需要创建付款单表头
    fun judgeNeedCreate() {
        val date = Date()
        val calendar = Calendar.getInstance()
        calendar.time = date
        val year = calendar.get(Calendar.YEAR)
        val isPresent = dataSourceRepo.findOne(DataSourceEntity::sourceType.equal(SourceType.PAYMENT)).isPresent
        if (!isPresent) {
            createPaymentDataBase(year)
        }
    }

    //判断是否需要创建收款单表头
    fun judgeNeedCreateReceiving() {
        val date = Date()
        val calendar = Calendar.getInstance()
        calendar.time = date
        val year = calendar.get(Calendar.YEAR)
//        val isPresent = dataSourceRepo.findOne(DataSourceEntity::sourceType.equal(SourceType.RECEIVING)).isPresent
//        if (!isPresent) {
        createReceivingDataBase(year)
//        }
    }

    //创建付款单数据表头
    fun createPaymentDataBase(year: Int) {
        val date = Date()
        val calendar = Calendar.getInstance()
        calendar.time = date

//        while (month >= 1) {
//            val name = "${month}月付款数据源"
        val name = "付款单二级明细表数据源"
//        val reportCategoryId = "5b4eb6d2de02f63889ff8762"
//        val headerItemList = createPaymentHeader()
        val headerItemList = createFirstPaymentHeader()
        val tableInfoHeader = TableInfoHeader(eid, name, PaymentTable.categoryId, headerItemList)

        val encryptData = encryptUtils.aesEncryptData(
                objectMapper.writeValueAsString(tableInfoHeader), aesKey)
        val requestBuilder = Request.Builder()
        val urlBuilder = HttpUrl.Builder()
        urlBuilder.scheme("http")
        urlBuilder.host("www.yunzhijia.com")
        urlBuilder.addPathSegment("gateway")
        urlBuilder.addPathSegment("open")
        urlBuilder.addPathSegment("linkerp")
        urlBuilder.addPathSegment("customizedapi")
        urlBuilder.addPathSegment("createTableInfoHeader")
        urlBuilder.addQueryParameter("accessToken", getAccessToken())
        requestBuilder.url(urlBuilder.build())
        val requestEntity = RequestEntity(encryptData)
        val entity = objectMapper.writeValueAsString(requestEntity)
        requestBuilder.post(RequestBody.create(MediaType.parse("application/json"), entity))
        val response = okHttpClient.newCall(requestBuilder.build()).execute()
        val responseBody = response.body()
        if (response.isSuccessful && responseBody != null) {
            val responseEntity = objectMapper.readValue(
                    responseBody.byteStream(), ResponseEntity::class.java)
            val decryptData = encryptUtils.aesDecryptData(responseEntity.data!!, aesKey)
            val createData = objectMapper.readValue(decryptData, CreateData::class.java)
            dataSourceRepo.save(DataSourceEntity(null, PaymentTable.categoryId, createData.tableInfoId, name, year, SourceType.RECEIVING))
//            println(createData.tableInfoId)
        }
    }

    //创建收款单数据表头
    fun createReceivingDataBase(year: Int) {
        val date = Date()
        val calendar = Calendar.getInstance()
        calendar.time = date

        val name = "收款单汇总数据源"
//        val reportCategoryId = "5b5ed7d8de02f61d7e17e555"
//        val headerItemList = createReceiverHeader()
        val headerTypeList = createReceiverType()
//        val headerTypeList = createFundHeader()

//        val tableInfoHeader = TableInfoHeader(eid, name, ReceivingTable.categoryId, headerItemList)

        val tableInfoHeader = TableInfoHeader(eid, name, ReceivingTable.categoryId, headerTypeList)
        val encryptData = encryptUtils.aesEncryptData(
                objectMapper.writeValueAsString(tableInfoHeader), aesKey)
        val requestBuilder = Request.Builder()
        val urlBuilder = HttpUrl.Builder()
        urlBuilder.scheme("http")
        urlBuilder.host("www.yunzhijia.com")
        urlBuilder.addPathSegment("gateway")
        urlBuilder.addPathSegment("open")
        urlBuilder.addPathSegment("linkerp")
        urlBuilder.addPathSegment("customizedapi")
        urlBuilder.addPathSegment("createTableInfoHeader")
        urlBuilder.addQueryParameter("accessToken", getAccessToken())
        requestBuilder.url(urlBuilder.build())
        val requestEntity = RequestEntity(encryptData)
        val entity = objectMapper.writeValueAsString(requestEntity)
        requestBuilder.post(RequestBody.create(MediaType.parse("application/json"), entity))
        val response = okHttpClient.newCall(requestBuilder.build()).execute()
        val responseBody = response.body()
        if (response.isSuccessful && responseBody != null) {
            val responseEntity = objectMapper.readValue(
                    responseBody.byteStream(), ResponseEntity::class.java)
            val decryptData = encryptUtils.aesDecryptData(responseEntity.data!!, aesKey)
            val createData = objectMapper.readValue(decryptData, CreateData::class.java)
            dataSourceRepo.save(DataSourceEntity(null, ReceivingTable.categoryId, createData.tableInfoId, name, year, SourceType.RECEIVING))
//            println(createData.tableInfoId)
        }
    }

    /**
     * 创建资金预算表头
     */
    fun createBudgetDataBase() {
        val date = Date()
        val calendar = Calendar.getInstance()
        calendar.time = date

        val name = "资金预算单据数据源"
//        val reportCategoryId = "5b5ed7d8de02f61d7e17e555"
//        val headerItemList = createBudgetHeader()
        val headerItemList = createFirstPaymentHeader()
        val tableInfoHeader = TableInfoHeader(eid, name, "5b8525f8de02f6717d1ff834", headerItemList)

        val encryptData = encryptUtils.aesEncryptData(
                objectMapper.writeValueAsString(tableInfoHeader), aesKey)
        val requestBuilder = Request.Builder()
        val urlBuilder = HttpUrl.Builder()
        urlBuilder.scheme("http")
        urlBuilder.host("www.yunzhijia.com")
        urlBuilder.addPathSegment("gateway")
        urlBuilder.addPathSegment("open")
        urlBuilder.addPathSegment("linkerp")
        urlBuilder.addPathSegment("customizedapi")
        urlBuilder.addPathSegment("createTableInfoHeader")
        urlBuilder.addQueryParameter("accessToken", getAccessToken())
        requestBuilder.url(urlBuilder.build())
        val requestEntity = RequestEntity(encryptData)
        val entity = objectMapper.writeValueAsString(requestEntity)
        requestBuilder.post(RequestBody.create(MediaType.parse("application/json"), entity))
        val response = okHttpClient.newCall(requestBuilder.build()).execute()
        val responseBody = response.body()
        if (response.isSuccessful && responseBody != null) {
            val responseEntity = objectMapper.readValue(
                    responseBody.byteStream(), ResponseEntity::class.java)
//            println(responseEntity)
            val decryptData = encryptUtils.aesDecryptData(responseEntity.data!!, aesKey)
            val createData = objectMapper.readValue(decryptData, CreateData::class.java)
            dataSourceRepo.save(DataSourceEntity(null, ReceivingTable.categoryId, createData.tableInfoId, name, 2018, SourceType.RECEIVING))
//            println(createData.tableInfoId)
        }
    }

    /**
     * 上传付款单一级明细表
     */
    @Scheduled(cron = "0 0 5 ? * *")
    fun synPaymentType() {
        uploadPaymentTypeSum(null, null)
    }


    fun uploadPaymentTypeSum(startTime: Date?, endTime: Date?) {
        //删除原有数据源

        val typeSumList = paymentBillService.getAllTypePaymentSum(startTime, endTime)
        val hashMapList = typeSumList.filter { it.expenseName != null }
                .filter { it.payMethod != null }
                .map {
                    val hashMap = HashMap<String, Any>()
                    val date = it.date
                    hashMap["recordId"] = it.id
                    hashMap["日期"] = date!!
                    hashMap["科目类型"] = it.expenseName!!
                    hashMap["所属集团"] = it.orgName!!
                    hashMap[it.payMethod!!] = it.amount!!
                    val calendar = Calendar.getInstance()
                    calendar.time = date
                    val year = calendar.get(Calendar.YEAR)
                    PaymentFirstDetail(encryptUtils.uuid(), date, it.orgName, it.expenseName, it.payMethod,
                            it.amount, Date(), year)
//                    hashMap
                }
        paymentFirstDetailRepo.saveAll(hashMapList)
//        uploadDataToBI(hashMapList, PaymentFirstTable.categoryId, PaymentFirstTable.tableInfoId)
    }

    /**
     * 上传付款单二级明细表
     */
    @Scheduled(cron = "0 0 5 ? * *")
    fun syncPaymentSum() {
        uploadPaymentSum(null, null)
    }


    fun uploadPaymentSum(startTime: Date?, endTime: Date?) {
        //删除原有数据源
//        deleteDataSource(PaymentSecondTable.tableInfoId)
        val paymentBillList = paymentBillService.getAllPaymentSumData(startTime, endTime)
        val hashMapList = paymentBillList.filter { it.expenseName != null }
                .filter { it.date != null }
                .filter { it.payMethod != null }
                .map {
                    val hashMap = HashMap<String, Any>()
                    val date = it.date
                    hashMap["recordId"] = it.id
                    hashMap["日期"] = date!!
                    hashMap[it.payMethod!!] = it.amount!!
                    hashMap["所属集团"] = it.orgName!!
                    hashMap["科目类型"] = it.expenseName!!

                    val calendar = Calendar.getInstance()
                    calendar.time = date
                    val year =calendar.get(Calendar.YEAR)

                    PaymentSecondDetail(encryptUtils.uuid(), date, it.orgName, it.expenseName, it.payMethod, it.amount, Date(),year)
//                    hashMap
                }
        paymentSecondDetailRepo.saveAll(hashMapList)
//        uploadDataToBI(hashMapList, PaymentSecondTable.categoryId, PaymentSecondTable.tableInfoId)
    }

    //上传日报付款单数据表数据
//    @Scheduled(cron = "0 0 4 ? * *")
    fun uploadPaymentTableInfo() {
        //删除原有数据源
//        deleteDataSource(PaymentTable.tableInfoId)
        val receiveList = ArrayList<PaymentEntity>()

        val allPaymentBillList = paymentBillService.getAllMonthPayment()
        receiveList.addAll(allPaymentBillList)
        val hashMapList = receiveList.filter { it.expenseName != null }
                .filter { it.date != null }.map {
                    val hashMap = HashMap<String, Any>()
                    val date = it.date
                    hashMap["recordId"] = it.id
                    hashMap["日期"] = date!!
                    hashMap[it.expenseName!!] = it.amount!!
                    hashMap["所属集团"] = it.orgName!!
                    it.payMethod?.let { hashMap["支付方式"] = it }
                    it.bankName?.let { hashMap["账户名称及开户行"] = it }
                    it.bankAccount?.let { hashMap["银行账号"] = it }
                    PaymentDetail(encryptUtils.uuid(), date, it.orgName, it.payMethod,
                            it.bankName, it.bankAccount, it.expenseName, it.amount, Date())
//                    hashMap
                }
        paymentDetailRepo.saveAll(hashMapList)
    }

    /**
     * 上传收款单汇总数据表
     */
    @Scheduled(cron = "0 0 5 ? * *")
    fun syncReceivingSum() {
        uploadReceivingSumData(null, null)
    }


    fun uploadReceivingSumData(startTime: Date?, endTime: Date?) {
        //删除原有数据源
//        deleteDataSource(ReceivingSumTable.tableInfoId)
//        receivingSummaryRepo.deleteAll()
        val receivingList = paymentBillService.getMonthReceivingList(startTime, endTime)

        val hashMapList = receivingList.filter { it.expenseName != null }
                .filter { it.payMethod != null }
                .map {
                    val hashMap = HashMap<String, Any>()
                    val date = it.date
                    hashMap["recordId"] = it.id
                    hashMap["日期"] = date!!
                    hashMap["科目类型"] = it.expenseName!!
                    hashMap["所属集团"] = it.orgName!!
                    hashMap[it.payMethod!!] = it.amount!!

                    val calendar = Calendar.getInstance()
                    calendar.time = date
                    val year =calendar.get(Calendar.YEAR)

                    ReceivingSummary(encryptUtils.uuid(), it.date, it.orgName,
                            it.expenseName, it.payMethod, it.amount, Date(),year)
                }
        receivingSummaryRepo.saveAll(hashMapList)
    }

    //上传收款单数据表
//    @Scheduled(cron = "0 0 5 ? * *")
    fun uploadReceivingTableInfo() {

        //删除原有数据源
//        deleteDataSource(ReceivingTable.tableInfoId)
//        receivingDetailRepo.deleteAll()
        val receivingBills = paymentBillService.getAllMonthReceivingData()
        val uploadTime = Date()
        val hashMapList = receivingBills.filter { it.expenseName != null }.filter { it.date != null }.map {
            val hashMap = HashMap<String, Any>()
            val date = it.date
            hashMap["recordId"] = it.id
            hashMap["日期"] = date!!
            val expenseName = when (it.expenseName) {
                "收集团内部公司转账" -> "集团内部公司转账"
                else -> it.expenseName
            }
            hashMap[expenseName!!] = it.amount!!
            hashMap["所属集团"] = it.orgName!!
            it.payMethod?.let { hashMap["支付方式"] = it }
            it.bankName?.let { hashMap["账户名称及开户行"] = it }
            it.bankAccount?.let { hashMap["银行账号"] = it }
            ReceivingDetail(encryptUtils.uuid(), it.date, it.orgName, it.payMethod,
                    it.bankName, it.bankAccount, expenseName, it.amount, uploadTime)
        }
        //调用报表秀秀提供的接口上传数据至报表秀秀平台
//        uploadDataToBI(hashMapList, ReceivingTable.categoryId, ReceivingTable.tableInfoId)
        receivingDetailRepo.saveAll(hashMapList)
    }

    /**
     * 调用报表秀秀提供的接口上传数据至报表秀秀平台
     */
    fun uploadDataToBI(hashMapList: List<HashMap<String, Any>>, categoryId: String, tableInfoId: String) {
        hashMapList.chunked(500).forEach {
            val tableInfoData = TableInfoData(eid, encryptUtils.uuid(), encryptUtils.uuid(), categoryId, tableInfoId,
                    objectMapper.writeValueAsString(it))

            val data = objectMapper.writeValueAsString(tableInfoData)
            val encryptData = encryptUtils.aesEncryptData(data, aesKey)
            val requestEntity = RequestEntity(encryptData)

            val urlBuilder = HttpUrl.Builder()
            val requestBuilder = Request.Builder()
            urlBuilder.scheme("https")
            urlBuilder.host("www.yunzhijia.com")
            urlBuilder.addPathSegment("gateway")
            urlBuilder.addPathSegment("open")
            urlBuilder.addPathSegment("linkerp")
            urlBuilder.addPathSegment("customizedapi")
            urlBuilder.addPathSegment("saveTableInfoData")
            urlBuilder.addQueryParameter("accessToken", getAccessToken())
            requestBuilder.url(urlBuilder.build())
            requestBuilder.post(RequestBody.create(MediaType.parse("application/json"),
                    objectMapper.writeValueAsString(requestEntity)))
            val response = okHttpClient.newCall(requestBuilder.build()).execute()
            val responseBody = response.body()
            if (response.isSuccessful && responseBody != null) {
                val responseEntity = objectMapper.readValue(
                        responseBody.byteStream(), ResponseEntity::class.java)
                println(responseEntity)
            } else {
                println("response-----------------------")
                println(response.body())
            }
        }
    }


    fun uploadDataToDB(hashMapList: List<HashMap<String, Any>>, categoryId: String, tableInfoId: String) {

    }

    fun createPaymentHeader(): List<HeaderItem> {

        val item1 = HeaderItem("recordId", "string")
        val item2 = HeaderItem("所属集团", "string")
        val payment1 = HeaderItem("支付方式", "string")
//        val payment2 = HeaderItem("账户名称及开户行", "string")
//        val payment3 = HeaderItem("银行账号", "string")
//        val item3 = HeaderItem("经营性资金流出", "number")
//        val item4 = HeaderItem("筹资活动资金流出", "number")
//        val item5 = HeaderItem("投资活动资金流出", "number")
//        val item6 = HeaderItem("其他资金流出", "number")

        val item7 = HeaderItem("原材料", "number")
        val item8 = HeaderItem("辅助材料", "number")
        val item9 = HeaderItem("电费", "number")
        val item10 = HeaderItem("水费及水资源费", "number")
        val item11 = HeaderItem("天然气、蒸汽", "number")
        val item12 = HeaderItem("环保、排污费", "number")
        val item13 = HeaderItem("委外加工费", "number")
        val item14 = HeaderItem("租赁费", "number")
        val item15 = HeaderItem("生产车辆使用费", "number")
        val item16 = HeaderItem("地产工程款", "number")
        val item17 = HeaderItem("运输费", "number")
        val item18 = HeaderItem("修理、维修费", "number")
        val item19 = HeaderItem("计量、检测费", "number")
        val item20 = HeaderItem("产品包装费", "number")
        val item21 = HeaderItem("生产性其他支出", "number")
        val item22 = HeaderItem("职工餐补", "number")
        val item23 = HeaderItem("非生产性其他支出", "number")
        val item24 = HeaderItem("上缴税金", "number")
        val item25 = HeaderItem("其他经营支出", "number")

        val item26 = HeaderItem("贷款本金", "number")
        val item27 = HeaderItem("理财本金", "number")
        val item28 = HeaderItem("外单位借款", "number")
        val item29 = HeaderItem("岗位股", "number")
        val item30 = HeaderItem("财务费用", "number")
        val item31 = HeaderItem("其他筹资支出", "number")


        val item32 = HeaderItem("固定资产支出", "number")
        val item33 = HeaderItem("无形资产支出", "number")
        val item34 = HeaderItem("在建工程", "number")
        val item35 = HeaderItem("短期投资", "number")
        val item36 = HeaderItem("长期投资", "number")
        val item37 = HeaderItem("其他投资", "number")

        val item38 = HeaderItem("其他及不可预见费用", "number")
        val item39 = HeaderItem("转入集团内部公司", "number")
        val item40 = HeaderItem("日期", "timestamp")

        return listOf(item1,
                item2, /*item3, item4, item5, item6, */item7, item8, item9, item10, item11,
                item12, item13, item14, item15, item16, item17, item18, item19, item20,
                item21, item22, item23, item24, item25, item26, item27, item28, item29,
                item30, item31, item32, item33, item34, item35, item36, item37, item38,
                item39, item40, payment1/*, payment2, payment3*/)
    }

    fun createFirstPaymentHeader(): List<HeaderItem> {
        val item1 = HeaderItem("recordId", "string")
        val item2 = HeaderItem("所属集团", "string")
        val payment1 = HeaderItem("科目类型", "string")
        val item3 = HeaderItem("电汇", "number")
        val item4 = HeaderItem("现金", "number")
        val item5 = HeaderItem("支票", "number")
        val item6 = HeaderItem("承兑", "number")
        val item7 = HeaderItem("其他", "number")
        val item40 = HeaderItem("日期", "timestamp")
        return listOf(item1, item2, payment1, item3, item4, item5, item6, item7, item40)
    }

    fun deletePaymentEntity() {
        paymentEntityRepo.deleteAll()
    }

    /**
     *删除收款单、付款单数据源数据
     */
    /*fun deleteDataSource(tableInfoId: String) {
        val requestBuilder = Request.Builder()
        val urlBuilder = HttpUrl.Builder()
        urlBuilder.scheme("https")
        urlBuilder.host("www.yunzhijia.com")
        urlBuilder.addPathSegment("gateway")
        urlBuilder.addPathSegment("open")
        urlBuilder.addPathSegment("linkerp")
        urlBuilder.addPathSegment("customizedapi")
        urlBuilder.addPathSegment("clearTableInfoData")
        urlBuilder.addQueryParameter("accessToken", getAccessToken())
        val hashMap = HashMap<String, String>()
        hashMap["eid"] = eid
        hashMap["tableInfoId"] = tableInfoId
        objectMapper.writeValueAsString(hashMap)
        val data = encryptUtils.aesEncryptData(objectMapper.writeValueAsString(hashMap), aesKey)
        val requestEntity = RequestEntity(data)
        requestBuilder.url(urlBuilder.build())
        requestBuilder.post(RequestBody.create(MediaType.parse("application/json"),
                objectMapper.writeValueAsString(requestEntity)))
        okHttpClient.newCall(requestBuilder.build()).execute()
    }
*/
    fun getAdminTableInfo() {
        val hashMap = HashMap<String, String>()
        hashMap["eid"] = eid
        val encryptData = encryptUtils.aesEncryptData(objectMapper.writeValueAsString(hashMap), aesKey)
        val requestEntity = RequestEntity(encryptData)

        val requestBuilder = Request.Builder()
        val urlBuilder = HttpUrl.Builder()
        urlBuilder.scheme("https")
        urlBuilder.host("www.yunzhijia.com")
        // /gateway/open/linkerp/ReportDataTableapi/getAdminTableInfos
        urlBuilder.addPathSegment("gateway")
        urlBuilder.addPathSegment("open")
        urlBuilder.addPathSegment("linkerp")
        urlBuilder.addPathSegment("ReportDataTableapi")
        urlBuilder.addPathSegment("getAdminTableInfos")
        urlBuilder.addQueryParameter("accessToken", getAccessToken())
        requestBuilder.url(urlBuilder.build())
        requestBuilder.post(RequestBody.create(MediaType.parse("application/json"),
                objectMapper.writeValueAsString(requestEntity)))

        val response = okHttpClient.newCall(requestBuilder.build()).execute()
        val responseBody = response.body()
        if (response.isSuccessful && responseBody != null) {
            val responseEntity = objectMapper.readValue(
                    responseBody.byteStream(), ResponseEntity::class.java)
            val decryptData = encryptUtils.aesDecryptData(responseEntity.data!!, aesKey)
            println(decryptData)
        }

    }

    fun deleteReceivingEntity() {
        receivingEntityRepo.deleteAll()
    }

    fun createReceiverHeader(): List<HeaderItem> {
        val item1 = HeaderItem("recordId", "string")
        val item2 = HeaderItem("所属集团", "string")
        val item3 = HeaderItem("支付方式", "string")
        val item4 = HeaderItem("账户名称及开户行", "string")
        val item5 = HeaderItem("银行账号", "string")

        val receive1 = HeaderItem("主营业务收入", "number")
        val receive2 = HeaderItem("收处置废旧物资款", "number")
        val receive3 = HeaderItem("融资现金流入", "number")
        val receive4 = HeaderItem("收其它款项", "number")
        val receive5 = HeaderItem("投资现金流入", "number")
        val receive6 = HeaderItem("收集团内部公司转款", "number")
        val item40 = HeaderItem("日期", "timestamp")
        return listOf(item1, item2, item3, item4, item5,
                receive1, receive2, receive3, receive4, receive5, receive6, item40)
    }

    fun createReceiverType(): List<HeaderItem> {
        val item1 = HeaderItem("recordId", "string")
        val item2 = HeaderItem("所属集团", "string")
        val item3 = HeaderItem("科目类型", "string")
        val receive1 = HeaderItem("电汇", "number")
        val receive2 = HeaderItem("现金", "number")
        val receive3 = HeaderItem("支票", "number")
        val receive4 = HeaderItem("承兑", "number")
        val receive5 = HeaderItem("其他", "number")
        val item40 = HeaderItem("日期", "timestamp")
        return listOf(item1, item2, item3, receive1, receive2, receive3, receive4, receive5, item40)
    }

    fun createBudgetHeader(): List<HeaderItem> {
        val item1 = HeaderItem("recordId", "string")
        val item2 = HeaderItem("所属集团", "string")
        val date = HeaderItem("日期", "timestamp")
        val payment = HeaderItem("支付方式", "string")
        val item3 = HeaderItem("经营资金流入", "number")
        val item4 = HeaderItem("主营业务回款", "number")
        val item5 = HeaderItem("出租业务回款", "number")
        val item6 = HeaderItem("废旧物资", "number")
        val item7 = HeaderItem("代收款项", "number")
        val item8 = HeaderItem("其他回款", "number")

        val item9 = HeaderItem("经营资金流出", "number")
        val item10 = HeaderItem("原材料", "number")
        val item11 = HeaderItem("机物料、备件", "number")
        val item12 = HeaderItem("电费", "number")
        val item13 = HeaderItem("水费及水资源费", "number")
        val item14 = HeaderItem("天然气、蒸汽", "number")
        val item15 = HeaderItem("环保、排污费", "number")
        val item16 = HeaderItem("委外加工费", "number")
        val item17 = HeaderItem("租赁费", "number")
        val item18 = HeaderItem("生产车辆使用费", "number")
        val item19 = HeaderItem("前期费用", "number")
        val item20 = HeaderItem("土地费用", "number")
        val item21 = HeaderItem("地产工程款", "number")
        val item22 = HeaderItem("运输费", "number")
        val item23 = HeaderItem("生产修理、维修费", "number")
        val item24 = HeaderItem("计量、检测费", "number")
        val item25 = HeaderItem("产品包装费", "number")
        val item26 = HeaderItem("生产性其他支出", "number")
        val item27 = HeaderItem("职工薪酬", "number")
        val item28 = HeaderItem("工资", "number")
        val item29 = HeaderItem("员工保险", "number")
        val item30 = HeaderItem("员工提成", "number")
        val item31 = HeaderItem("劳务费", "number")
        val item32 = HeaderItem("统筹外", "number")
        val item33 = HeaderItem("遗属救济金", "number")
        val item34 = HeaderItem("食堂费用", "number")
        val item35 = HeaderItem("职工餐补", "number")
        val item36 = HeaderItem("劳保、福利费", "number")

        val item37 = HeaderItem("非生产性其他支出", "number")
        val item38 = HeaderItem("电话费", "number")
        val item39 = HeaderItem("通讯补", "number")
        val item40 = HeaderItem("办公用品", "number")
        val item41 = HeaderItem("印刷费", "number")
        val item42 = HeaderItem("电脑及网络维修", "number")
        val item43 = HeaderItem("网络服务费", "number")
        val item44 = HeaderItem("非生产车辆费用", "number")
        val item45 = HeaderItem("招待费", "number")
        val item46 = HeaderItem("差旅费", "number")
        val item47 = HeaderItem("市内交通费", "number")
        val item48 = HeaderItem("招聘、培训费", "number")
        val item49 = HeaderItem("诉讼费", "number")
        val item50 = HeaderItem("协会会费", "number")
        val item51 = HeaderItem("质量认证费", "number")
        val item52 = HeaderItem("审计评估费", "number")
        val item53 = HeaderItem("咨询费", "number")
        val item54 = HeaderItem("教育培训", "number")
        val item55 = HeaderItem("广告宣传", "number")
        val item56 = HeaderItem("绿化费用", "number")
        val item57 = HeaderItem("劳工费", "number")
        val item58 = HeaderItem("非生产修理、维修费", "number")
        val item59 = HeaderItem("物业费", "number")
        val item60 = HeaderItem("取暖费", "number")
        val item61 = HeaderItem("年检费", "number")
        val item62 = HeaderItem("清洁费", "number")
        val item63 = HeaderItem("洗涤费", "number")
        val item64 = HeaderItem("考察费", "number")
        val item65 = HeaderItem("服装费", "number")
        val item66 = HeaderItem("招生提成", "number")
        val item67 = HeaderItem("招生费用", "number")
        val item68 = HeaderItem("勤工俭学支出", "number")
        val item69 = HeaderItem("班费支出", "number")
        val item70 = HeaderItem("垃圾清运费", "number")
        val item71 = HeaderItem("保险费", "number")
        val item72 = HeaderItem("探亲费", "number")
        val item73 = HeaderItem("体检费", "number")
        val item74 = HeaderItem("低值易耗品", "number")
        val item75 = HeaderItem("物料消耗", "number")
        val item76 = HeaderItem("草坪养护", "number")
        val item77 = HeaderItem("草坪机械配件", "number")
        val item78 = HeaderItem("草坪机械附属用油", "number")
        val item79 = HeaderItem("企业文化费", "number")
        val item80 = HeaderItem("非生产其他支出", "number")
        val item81 = HeaderItem("备用金往来", "number")

        val item82 = HeaderItem("上缴税费", "number")
        val item83 = HeaderItem("增值税、营业税", "number")
        val item84 = HeaderItem("城建及教育附加", "number")
        val item85 = HeaderItem("房产、土地税", "number")
        val item86 = HeaderItem("河套基金", "number")
        val item87 = HeaderItem("所得税", "number")
        val item88 = HeaderItem("印花税", "number")
        val item89 = HeaderItem("工会经费", "number")
        val item90 = HeaderItem("代收代付款", "number")
        val item91 = HeaderItem("财务费用", "number")
        val item92 = HeaderItem("银行手续费", "number")
        val item93 = HeaderItem("贷款利息", "number")
        val item94 = HeaderItem("贷款担保费", "number")
        val item95 = HeaderItem("内部借款及其它费用", "number")
        val item96 = HeaderItem("内部借款利息", "number")

        val item97 = HeaderItem("其他支出", "number")
        val item98 = HeaderItem("经营资金净额", "number")

        val item99 = HeaderItem("投资收入", "number")
        val item100 = HeaderItem("收回投资", "number")
        val item101 = HeaderItem("取得投资收益", "number")
        val item102 = HeaderItem("处置固定、无形、其他资产", "number")
        val item103 = HeaderItem("收到其他投资活动的回款", "number")
        val item104 = HeaderItem("投资支出", "number")

        val item105 = HeaderItem("货币投资", "number")
        val item106 = HeaderItem("固定资产支出", "number")
        val item107 = HeaderItem("按揭款", "number")
        val item108 = HeaderItem("无形资产支出", "number")
        val item109 = HeaderItem("在建工程", "number")
        val item110 = HeaderItem("投资净额", "number")

        val item111 = HeaderItem("融资流入", "number")
        val item112 = HeaderItem("银行借款", "number")
        val item113 = HeaderItem("外单位借款", "number")
        val item114 = HeaderItem("内部借款", "number")
        val item115 = HeaderItem("岗位股", "number")
        val item116 = HeaderItem("融资支出", "number")
        val item117 = HeaderItem("还银行借款", "number")
        val item118 = HeaderItem("还外单位借款", "number")
        val item119 = HeaderItem("退内部借款", "number")
        val item120 = HeaderItem("退岗位股", "number")
        val item121 = HeaderItem("融资净额", "number")
        val item122 = HeaderItem("上市费用", "number")
        val item123 = HeaderItem("国企改制", "number")
        val item124 = HeaderItem("国企改制费用", "number")
        val item125 = HeaderItem("不在岗人员费用", "number")
        val item126 = HeaderItem("集团往来", "number")
        val item127 = HeaderItem("上交（转回）集团", "number")
        val item128 = HeaderItem("集团拨入", "number")
        val item129 = HeaderItem("资金总收入", "number")
        val item130 = HeaderItem("资金总支出", "number")
        val item131 = HeaderItem("上期资金余额", "number")
        val item132 = HeaderItem("资金累计结余", "number")


        return listOf(item1, item2, date, payment, item3, item4, item5, item6, item7, item8, item9, item10,
                item11, item12, item13, item14, item15, item16, item17, item18, item19, item20,
                item21, item22, item23, item24, item25, item26, item27, item28, item29, item30,
                item31, item32, item33, item34, item35, item36, item37, item38, item39, item40,
                item41, item42, item43, item44, item45, item46, item47, item48, item49, item50,
                item51, item52, item53, item54, item55, item56, item57, item58, item59, item60,
                item61, item62, item63, item64, item65, item66, item67, item68, item69, item70,
                item71, item72, item73, item74, item75, item76, item77, item78, item79, item80,
                item81, item82, item83, item84, item85, item86, item87, item88, item89, item90,
                item91, item92, item93, item94, item95, item96, item97, item98, item99, item100,
                item101, item102, item103, item104, item105, item106, item107, item108, item109, item110,
                item111, item112, item113, item114, item115, item116, item117, item118, item119, item120,
                item121, item122, item123, item124, item125, item126, item127, item128, item129, item130,
                item131, item132)
    }

    //    @Scheduled(cron = "0 30 5 ? * *")
    fun getBudgetData() {
//        val tBgForm = tBgBgFormRepo.findAll(TBgBgForm::fnumber.equal("FC01JT201808")).first()
//        deleteDataSource(BudgetTable.tableInfoId)
        val calendar = Calendar.getInstance()
        calendar.set(Calendar.YEAR, 2018)
        calendar.set(Calendar.MONTH, 1)
        calendar.set(Calendar.DAY_OF_MONTH, 1)
//        val date = calendar.time
        val templateIds = tBgBgTemplateRepo.findAll(TBgBgTemplate::fnumber.equal("001")).map { it.fid!! }
        val tBgFormList = tBgBgFormRepo.findAll(TBgBgForm::fyear.equal(2018)
                and TBgBgForm::fstate.equal(2)
                and TBgBgForm::fbgtemplateid.`in`(templateIds)
                and TBgBgForm::fcontrolunitid.equal("sVsAAAAACzLM567U")).toList()
        val baseUnitList = tOrgBaseUnitRepo
                .findAll(TOrgBaseUnit::fid.`in`(tBgFormList.map { it.fcontrolunitid!! }.toSet()))
        val hashMapList = ArrayList<HashMap<String, Any>>()

        val sampleData = HashSet<String>()

        tBgFormList.forEach { tBgForm ->
            val tBgDataList = tBgBgDataRepo.findAll(TBgBgData::fbgformid.equal(tBgForm.fid)).toList()
            val recordList = tBgBgCtrlRecordRepo
                    .findAll(TBgBgCtrlRecord::fitemformula.`in`(tBgDataList.map { it.fformula!! })).toList()

            val baseUnit = baseUnitList.find { it.fid == tBgForm.fcontrolunitid }

            val itemFormula = recordList.filter { it.fitemformula != null }.map { it.fitemformula }.toSet()

            val mapList = itemFormula.map { formula ->
                val record = recordList.find { it.fitemformula == formula }
                val dataInfo = tBgDataList.find { it.fformula == record?.fitemformula }
                val hashMap = HashMap<String, Any>()
                if (dataInfo != null) {
                    println("------------------------record-------------")
                    println(record?.fitemname)
                    println("-----------------datainfo.fid---------------")
                    println(dataInfo.fid)
                    println("---------------datainfor.bgvalue------------")
                    println(dataInfo.fbgvalue)
                    println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")

                    val expenseName: String = when {
                        record?.fitemname == "代付款项" -> "代收代付款"
                        record?.fitemname == "生产性修理、维修费" -> "生产修理、维修费"
                        else -> record?.fitemname!!
                    }

                    hashMap[expenseName] = dataInfo.fbgvalue!!
                    sampleData += expenseName
                    hashMap["recordId"] = encryptUtils.uuid()
                    calendar.set(Calendar.YEAR, 2018)
                    calendar.set(Calendar.MONTH, tBgForm.fperiod!!)
                    calendar.set(Calendar.DAY_OF_MONTH, 1)
                    hashMap["日期"] = calendar.time
                    hashMap["所属集团"] = baseUnit?.fnameL2!!
                }
//                println("------------------------record-------------")
//                println(hashMap)
//                println("-----------------datainfo.fid---------------")
                hashMap
            }

            hashMapList += mapList
        }

        val stdData = testItem()
        println(sampleData.intersect(stdData))//匹配成功
        println(sampleData.subtract(stdData))//仅方案中存在
        println(stdData.subtract(sampleData))//仅基础资料存在
        hashMapList.filter { it.containsKey("非生产修理、维修费") }.chunked(500).forEach {
            println(it)
            val tableInfoData = TableInfoData(eid, encryptUtils.uuid(), encryptUtils.uuid(),
                    BudgetTable.categoryId, BudgetTable.tableInfoId,
                    objectMapper.writeValueAsString(it))
            val encryptData = encryptUtils.aesEncryptData(objectMapper.writeValueAsString(tableInfoData), aesKey)
            val requestEntity = RequestEntity(encryptData)

            val urlBuilder = HttpUrl.Builder()
            val requestBuilder = Request.Builder()
            urlBuilder.scheme("https")
            urlBuilder.host("www.yunzhijia.com")
            urlBuilder.addPathSegment("gateway")
            urlBuilder.addPathSegment("open")
            urlBuilder.addPathSegment("linkerp")
            urlBuilder.addPathSegment("customizedapi")
            urlBuilder.addPathSegment("saveTableInfoData")
            urlBuilder.addQueryParameter("accessToken", getAccessToken())
            requestBuilder.url(urlBuilder.build())
            requestBuilder.post(RequestBody.create(MediaType.parse("application/json"),
                    objectMapper.writeValueAsString(requestEntity)))
            okHttpClient.newCall(requestBuilder.build()).enqueue(OkHttpCallbackStub())
        }
    }

    /**
     * 上传资金预算表数据
     */
    @Scheduled(cron = "0 0 5 ? * *")
    fun syncBudget() {
        getBudget(null, null)
    }

    fun getBudget(startTime: Date?, endTime: Date?) {
        //删除资金预算表数据
//        deleteDataSource(BudgetTable.tableInfoId)
        val budgetList = paymentBillService.getBudgetDataActual(startTime, endTime)
        val hashMapList = budgetList
                .filter { it.titleName != null }
                .filter { it.date != null }
                .filter { it.payMethod != null }
                .map {
                    val expenseName: String = when (it.titleName) {
                        "代付款项" -> "代收代付款"
                        "生产性修理、维修费" -> "生产修理、维修费"
                        else -> it.titleName!!
                    }
                    val hashMap = HashMap<String, Any>()
                    val date = it.date
                    hashMap["recordId"] = encryptUtils.uuid()
                    hashMap["日期"] = date!!
                    hashMap["科目类型"] = expenseName
                    hashMap[it.payMethod!!] = it.account!!.divide(BigDecimal(10000))
                    hashMap["所属集团"] = it.orgName!!
                    val calendar = Calendar.getInstance()
                    calendar.time = date
                    val year =calendar.get(Calendar.YEAR)

                    BudgetDB(encryptUtils.uuid(), date, it.orgName, expenseName, it.payMethod, it.account,
                            Date(),year)
//                    hashMap
                }
        budgetDBRepo.saveAll(hashMapList)
//        uploadDataToBI(hashMapList, BudgetTable.categoryId, BudgetTable.tableInfoId)
    }


    /**
     * 上传收支汇总数据源
     */
    @Scheduled(cron = "0 0 5 ? * *")
    fun syncFunSum() {
        uploadFundSum(null, null)
    }


    fun uploadFundSum(startTime: Date?, endTime: Date?) {
        //删除数据源
//        deleteDataSource(FundSumTable.tableInfoId)
        val fundSummaryList = paymentBillService.getFundSummaryData(startTime, endTime)

        val hashMapList = fundSummaryList
                .filter { it.payName != null }
                .filter { it.date != null }
                .map {
                    val fundType = when (it.fundType) {
                        FundType.PAYMENT -> "收入"
                        else -> "支出"
                    }
                    val hashMap = HashMap<String, Any>()
                    val date = it.date
                    hashMap["recordId"] = encryptUtils.uuid()
                    hashMap["日期"] = date!!
                    hashMap[it.payName!!] = it.payAccount!!.divide(BigDecimal(10000))
                    hashMap["所属集团"] = it.orgName!!
                    hashMap["资金类型"] = fundType
                    val calendar = Calendar.getInstance()
                    calendar.time = date
                    val year = calendar.get(Calendar.YEAR)

                    IncomeExpenseSummary(encryptUtils.uuid(), date, it.orgName, fundType, it.payName, it.payAccount, Date(), year)
                }
        incomeExpenseSummaryRepo.saveAll(hashMapList)
//        uploadDataToBI(hashMapList, FundSumTable.categoryId, FundSumTable.tableInfoId)
    }

    fun createFundHeader(): List<HeaderItem> {
        val item1 = HeaderItem("recordId", "string")
        val item2 = HeaderItem("所属集团", "string")

        val receive1 = HeaderItem("资金类型", "string")
        val receive2 = HeaderItem("电汇总额", "number")
        val receive3 = HeaderItem("支票总额", "number")
        val receive4 = HeaderItem("承兑总额", "number")
        val receive5 = HeaderItem("现金总额", "number")
        val receive6 = HeaderItem("其他总额", "number")
        val item40 = HeaderItem("日期", "timestamp")
        return listOf(item1, item2, receive1, item40, receive2, receive3, receive4, receive5, receive6)
    }

    fun testItem(): Set<String?> {
        val itemList = tBgBgCtrlRecordRepo
                .findAll().map { it.fitemname }.toSet()
        println("***************************itemList****************************")
        return itemList
    }
}

